/*
 * C
 *
 * Copyright 2018-2023 MicroEJ Corp. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be found with this software.
 */

/**
 * @file
 * @brief LLNET_SSL_ERRORS implementation over mbedtls.
 * @author MicroEJ Developer Team
 * @version 2.1.7
 * @date 7 April 2023
 */

#if !defined(MBEDTLS_CONFIG_FILE)
#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
#include "mbedtls/aes.h"
#include "mbedtls/asn1.h"
#include "mbedtls/base64.h"
#include "mbedtls/bignum.h"
#include "mbedtls/blowfish.h"
#include "mbedtls/camellia.h"
#include "mbedtls/ccm.h"
#include "mbedtls/cipher.h"
#include "mbedtls/ctr_drbg.h"
#include "mbedtls/des.h"
#include "mbedtls/dhm.h"
#include "mbedtls/ecp.h"
#include "mbedtls/entropy.h"
#include "mbedtls/gcm.h"
#include "mbedtls/hmac_drbg.h"
#include "mbedtls/md.h"
#include "mbedtls/net_sockets.h"
#include "mbedtls/oid.h"
#include "mbedtls/padlock.h"
#include "mbedtls/pem.h"
#include "mbedtls/pk.h"
#include "mbedtls/pkcs12.h"
#include "mbedtls/pkcs5.h"
#include "mbedtls/rsa.h"
#include "mbedtls/ssl.h"
#include "mbedtls/threading.h"
#include "mbedtls/x509.h"
#include "mbedtls/xtea.h"
#include "LLNET_SSL_CONSTANTS.h"
#include "LLNET_SSL_ERRORS.h"
#include "sni.h"

#ifdef __cplusplus
	extern "C" {
#endif

/* -- Mbed TLS unsupported error return */
/*
J_WINCRYPT_ERROR
J_CRYPTGEN_ERROR
J_RAN_BLOCK_ERROR
J_ISSUER_ERROR
J_ASN_VERSION_ERROR
J_ASN_RSA_KEY_ERROR
J_ASN_OBJECT_ID_ERROR
J_ASN_EXPECT_0_ERROR
J_ASN_BITSTR_ERROR
J_ASN_UNKNOWN_OID_ERROR
J_ASN_DATE_SZ_ERROR
J_ASN_BEFORE_DATE_ERROR
J_ASN_AFTER_DATE_ERROR
J_ASN_SIG_OID_ERROR
J_ASN_TIME_ERROR
J_ASN_SIG_CONFIRM_ERROR
J_ASN_SIG_HASH_ERROR
J_ASN_SIG_KEY_ERROR
J_ASN_DH_KEY_ERROR
J_ASN_NTRU_KEY_ERROR
J_ASN_CRIT_EXT_ERROR
J_ASN_ECC_KEY_ERROR
J_ECC_BAD_ARG_ERROR
J_ECC_CURVE_OID_ERROR
J_ASN_NO_SIGNER_ERROR
J_ASN_CRL_CONFIRM_ERROR
J_ASN_CRL_NO_SIGNER_ERROR
J_ASN_OCSP_CONFIRM_ERROR
J_ALT_NAME_ERROR
J_CAVIUM_INIT_ERROR
J_BAD_ENC_STATE_ERROR
J_REQ_ATTRIBUTE_ERROR
J_PKCS7_OID_ERROR
J_PKCS7_RECIP_ERROR
J_FIPS_NOT_ALLOWED_ERROR
J_ASN_NAME_INVALID_ERROR
J_HMAC_MIN_KEYLEN_ERROR
J_LENGTH_ONLY_ERROR
J_IN_CORE_FIPS_ERROR
J_AES_KAT_FIPS_ERROR
J_DES3_KAT_FIPS_ERROR
J_HMAC_KAT_FIPS_ERROR
J_RSA_KAT_FIPS_ERROR
J_DRBG_KAT_FIPS_ERROR
J_DRBG_CONT_FIPS_ERROR
J_AESGCM_KAT_FIPS_ERROR
J_SIDE_ERROR
J_NO_PEER_KEY
J_VERIFY_MAC_ERROR
J_INCOMPLETE_DATA
J_UNKNOWN_RECORD_TYPE
J_FATAL_ERROR
J_NO_DH_PARAMS
J_BUILD_MSG_ERROR
J_DOMAIN_NAME_MISMATCH
J_NOT_READY_ERROR
J_SERVER_HINT_ERROR
J_PSK_KEY_ERROR
NTRU_KEY_ERROR
J_NTRU_DRBG_ERROR
J_NTRU_ENCRYPT_ERROR
J_NTRU_DECRYPT_ERROR
J_ECC_EXPORT_ERROR
J_ECC_SHARED_ERROR
J_OCSP_CERT_REVOKED
J_CRL_CERT_REVOKED
J_CRL_MISSING
J_OCSP_NEED_URL
J_OCSP_CERT_UNKNOWN
J_OCSP_LOOKUP_FAIL
J_MAX_CHAIN_ERROR
J_SANITY_CIPHER_ERROR
J_OUT_OF_ORDER_ERROR
J_BAD_KEA_TYPE_ERROR
J_RECV_OVERFLOW_ERROR
J_UNKNOWN_HOST_NAME_ERROR
J_KEYUSE_SIGNATURE_ERROR
J_KEYUSE_ENCIPHER_ERROR
J_EXTKEYUSE_AUTH_ERROR
J_SCR_DIFFERENT_CERT_ERROR
J_SEND_OOB_READ_ERROR
J_SANITY_MSG_ERROR
J_DUPLICATE_MSG_ERROR
J_BAD_ENCODED_CERT_FORMAT
J_DECRYPT_ERROR
*/


jint LLNET_SSL_TranslateReturnCode(int32_t mbedtls_error) {

	LLNET_SSL_DEBUG_TRACE("%s(SSL_error=%d)\n", __func__, mbedtls_error);
	switch (mbedtls_error) {

	case 0:
		return J_SSL_NO_ERROR;

	/* Generic error, no specific error for open */
	case MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED:
		return J_OPEN_RAN_ERROR;

	case MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR:
		return J_READ_RAN_ERROR;

	case MBEDTLS_ERR_RSA_BAD_INPUT_DATA:
		return J_RSA_WRONG_TYPE_ERROR;

	case MBEDTLS_ERR_RSA_KEY_GEN_FAILED:
		return J_RSA_BUFFER_ERROR;

	case MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE:
		return J_BUFFER_ERROR;

	case MBEDTLS_ERR_RSA_VERIFY_FAILED:
		return J_ALGO_ID_ERROR;

	case MBEDTLS_ERR_RSA_PUBLIC_FAILED:
		return J_PUBLIC_KEY_ERROR;


	case MBEDTLS_ERR_X509_INVALID_DATE:
		return J_DATE_ERROR;

	/* mbedtls have same error for J_SUBJECT_ERROR than J_ISSUER_ERROR*/
	case MBEDTLS_ERR_X509_INVALID_NAME:
		return J_SUBJECT_ERROR;

	case MBEDTLS_ERR_X509_INVALID_SIGNATURE:
		return J_CA_TRUE_ERROR;

	case MBEDTLS_ERR_X509_INVALID_EXTENSIONS:
		return J_EXTENSIONS_ERROR;

	case MBEDTLS_ERR_ASN1_OUT_OF_DATA:
		return J_CERT_PARSE_ERROR;

	case MBEDTLS_ERR_ASN1_INVALID_DATA:
		return J_ASN_GETINT_ERROR;

	case MBEDTLS_ERR_ASN1_UNEXPECTED_TAG:
		return J_ASN_TAG_NULL_ERROR;

	case MBEDTLS_ERR_ASN1_INVALID_LENGTH:
		return J_ASN_INPUT_ERROR;

	case MBEDTLS_ERR_MPI_BAD_INPUT_DATA:
	case MBEDTLS_ERR_CCM_BAD_INPUT:
	case MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA:
	case MBEDTLS_ERR_DHM_BAD_INPUT_DATA:
	case MBEDTLS_ERR_GCM_BAD_INPUT:
	case MBEDTLS_ERR_MD_BAD_INPUT_DATA:
	case MBEDTLS_ERR_PEM_BAD_INPUT_DATA:
	case MBEDTLS_ERR_PK_BAD_INPUT_DATA:
	case MBEDTLS_ERR_PKCS12_BAD_INPUT_DATA:
	case MBEDTLS_ERR_PKCS5_BAD_INPUT_DATA:
	case MBEDTLS_ERR_THREADING_BAD_INPUT_DATA:
		return J_BAD_FUNC_ARG;

	case MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE:
	case MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE:
	case MBEDTLS_ERR_PEM_FEATURE_UNAVAILABLE:
	case MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE:
	case MBEDTLS_ERR_PKCS12_FEATURE_UNAVAILABLE:
	case MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE:
	case MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE:
	case MBEDTLS_ERR_THREADING_FEATURE_UNAVAILABLE:
	case MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE:
		return J_NOT_COMPILED_IN;

	case MBEDTLS_ERR_PEM_PASSWORD_MISMATCH:
	case MBEDTLS_ERR_PK_PASSWORD_MISMATCH:
	case MBEDTLS_ERR_PKCS12_PASSWORD_MISMATCH:
	case MBEDTLS_ERR_PKCS5_PASSWORD_MISMATCH:
		return J_UNICODE_SIZE_ERROR;

	case MBEDTLS_ERR_PEM_PASSWORD_REQUIRED:
	case MBEDTLS_ERR_PK_PASSWORD_REQUIRED:
		return J_NO_PASSWORD;

	case MBEDTLS_ERR_GCM_AUTH_FAILED:
		return J_AES_GCM_AUTH_ERROR;

	case MBEDTLS_ERR_CCM_AUTH_FAILED:
		return J_AES_CCM_AUTH_ERROR;

	case MBEDTLS_ERR_PADLOCK_DATA_MISALIGNED:
		return J_BAD_ALIGN_ERROR;

	case MBEDTLS_ERR_CIPHER_INVALID_PADDING:
		return J_BAD_PADDING_ERROR;

	case MBEDTLS_ERR_RSA_RNG_FAILED:
	case MBEDTLS_ERR_SSL_NO_RNG:
		return J_RNG_FAILURE_ERROR;

	case MBEDTLS_ERR_RSA_INVALID_PADDING:
		return J_RSA_PAD_ERROR;

	case MBEDTLS_ERR_SSL_UNKNOWN_CIPHER:
		return J_UNSUPPORTED_SUITE;

	case MBEDTLS_ERR_SSL_NO_CIPHER_CHOSEN:
		return J_MATCH_SUITE_ERROR;

	case MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH:
	case MBEDTLS_ERR_BLOWFISH_INVALID_INPUT_LENGTH:
	case MBEDTLS_ERR_CAMELLIA_INVALID_INPUT_LENGTH:
	case MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG:
	case MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH:
	case MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG:
	case MBEDTLS_ERR_X509_BAD_INPUT_DATA:
	case MBEDTLS_ERR_XTEA_INVALID_INPUT_LENGTH:
		return J_INPUT_CASE_ERROR;

	case MBEDTLS_ERR_AES_INVALID_KEY_LENGTH:
	case MBEDTLS_ERR_BLOWFISH_INVALID_KEY_LENGTH:
	case MBEDTLS_ERR_CAMELLIA_INVALID_KEY_LENGTH:
		return J_PREFIX_ERROR;

	case MBEDTLS_ERR_CIPHER_ALLOC_FAILED:
	case MBEDTLS_ERR_DHM_ALLOC_FAILED:
	case MBEDTLS_ERR_MD_ALLOC_FAILED:
	case MBEDTLS_ERR_X509_ALLOC_FAILED:
	case MBEDTLS_ERR_MPI_ALLOC_FAILED:
	case MBEDTLS_ERR_ASN1_ALLOC_FAILED:
	case MBEDTLS_ERR_ECP_ALLOC_FAILED:
	case MBEDTLS_ERR_PK_ALLOC_FAILED:
	case MBEDTLS_ERR_SSL_ALLOC_FAILED:
		return J_MEMORY_ERROR;

	case MBEDTLS_ERR_SSL_INVALID_VERIFY_HASH:
		return J_VERIFY_FINISHED_ERROR;

	case MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO:
		return J_HEADER_PARSE_ERROR;

	case MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE:
	case MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST:
	case MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY:
		return J_NO_PEER_CERT;

	case MBEDTLS_ERR_SSL_BAD_HS_PROTOCOL_VERSION:
		return J_UNKNOWN_HANDSHAKE_TYPE;

	case MBEDTLS_ERR_NET_SOCKET_FAILED:
	case MBEDTLS_ERR_NET_CONNECT_FAILED:
	case MBEDTLS_ERR_NET_BIND_FAILED:
	case MBEDTLS_ERR_NET_LISTEN_FAILED:
	case MBEDTLS_ERR_NET_ACCEPT_FAILED:
	case MBEDTLS_ERR_NET_SEND_FAILED:
	case MBEDTLS_ERR_NET_CONN_RESET:
	case MBEDTLS_ERR_NET_UNKNOWN_HOST:
		return J_SOCKET_ERROR;

	case MBEDTLS_ERR_NET_RECV_FAILED:
	case MBEDTLS_ERR_NET_BUFFER_TOO_SMALL:
	case MBEDTLS_ERR_NET_INVALID_CONTEXT:
		return J_SOCKET_NODATA;

	case MBEDTLS_ERR_PEM_UNKNOWN_ENC_ALG:
	case MBEDTLS_ERR_PK_TYPE_MISMATCH:
		return J_ENCRYPT_ERROR;

	case MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED:
		return J_NO_PRIVATE_KEY;

	case MBEDTLS_ERR_RSA_PRIVATE_FAILED:
		return J_RSA_PRIVATE_ERROR;

	case MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO:
		return J_BAD_HELLO;

	case MBEDTLS_ERR_SSL_WANT_READ:
		return J_WANT_READ;

	case MBEDTLS_ERR_SSL_WANT_WRITE:
		return J_WANT_WRITE;

	case MBEDTLS_ERR_PK_KEY_INVALID_VERSION:
		return J_PMS_VERSION_ERROR;

	case MBEDTLS_ERR_X509_INVALID_VERSION:
	case MBEDTLS_ERR_X509_UNKNOWN_VERSION:
		return J_VERSION_ERROR;

	case MBEDTLS_ERR_ASN1_BUF_TOO_SMALL:
	case MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL:
	case MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL:
	case MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL:
	case MBEDTLS_ERR_OID_BUF_TOO_SMALL:
	case MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL:
	case MBEDTLS_ERR_X509_BUFFER_TOO_SMALL:
		return J_MALFORMED_BUFFER;

	case MBEDTLS_ERR_X509_CERT_VERIFY_FAILED:
		return J_VERIFY_CERT_ERROR;

	case MBEDTLS_ERR_X509_SIG_MISMATCH:
		return J_VERIFY_SIGN_ERROR;

	case MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY:
		return J_CLIENT_ID_ERROR;

	case MBEDTLS_ERR_SSL_BAD_INPUT_DATA:
		return J_LENGTH_ERROR;

	case MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE:
		return J_PEER_KEY_ERROR;

	case MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY:
		return J_ZERO_RETURN;

	case MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE:
		return J_ECC_CURVETYPE_ERROR;

	case MBEDTLS_ERR_ECP_BAD_INPUT_DATA:
		return J_ECC_CURVE_ERROR;

	case MBEDTLS_ERR_ECP_INVALID_KEY:
		return J_ECC_PEERKEY_ERROR;

	case MBEDTLS_ERR_ECP_RANDOM_FAILED:
		return J_ECC_MAKEKEY_ERROR;

	case MBEDTLS_ERR_SSL_CA_CHAIN_REQUIRED:
		return J_NO_TRUSTED_CERT;

	case MBEDTLS_ERR_PEM_ALLOC_FAILED:
		return J_BAD_CERT_MANAGER_ERROR;

	case MBEDTLS_ERR_SSL_NO_USABLE_CIPHERSUITE:
		return J_SUITES_ERROR;

	case MBEDTLS_ERR_PEM_INVALID_DATA:
		return J_SSL_NO_PEM_HEADER;

	case MBEDTLS_ERR_SSL_PEER_VERIFY_FAILED:
		return J_NO_PEER_VERIFY;

	case MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO:
		return J_SECURE_RENEGOTIATION_ERROR;

	case MBEDTLS_ERR_SSL_BAD_HS_CHANGE_CIPHER_SPEC:
		return J_NO_CHANGE_CIPHER_ERROR;

	case MBEDTLS_ERR_X509_INVALID_FORMAT :
		return J_BAD_CERTTYPE;

	default:
		return J_UNKNOWN_ERROR;
	}

}

#ifdef __cplusplus
	}
#endif
